/**
 * @file     startup_stm32f10x_hd.c
 * @author   SummerBreeze630 (2538999495@qq.com)
 * @brief    STM32F10x High Density Devices startup file for GCC toolchain.
 * @version  1.0.0
 * @date     2025-10-20
 *
 * @copyright Copyright (c) 2025-2025 SummerBreeze630
 *
 */

#include <stddef.h>
#include <stdint.h>

// some gnu-c extensions attributes
#define __weak __attribute__((weak))
#define __alias(x) __attribute__((alias(#x)))
#define __noreturn __attribute__((noreturn))
#define __used __attribute__((used))
#define __section(x) __attribute__((section(#x)))

/* Symbols Defined in Linker Script */
extern uint8_t _estack[]; /** Top of Stack Pointer */

extern uint8_t _sidata[]; /**< Start address for .data initialization values (in Flash) */
extern uint8_t _sdata[];  /**< Start address for .data section (in RAM) */
extern uint8_t _edata[];  /**< End address for .data section (in RAM) */
extern uint8_t _sbss[];   /**< Start address for .bss section (in RAM) */
extern uint8_t _ebss[];   /**< End address for .bss section (in RAM) */

/** Specific value for RAM boot mode */
static const uint32_t BootRAM = 0xF1E0F85F;

/** Interrupt handler function pointer type definition */
typedef void (*interruptHandlerType)(void);

/* External function declarations */
extern void SystemInit(void);        /**< Defined in system_stm32f1xx.c */
extern int main(void);               /**< Defined in main.c */
extern void __libc_init_array(void); /**< Newlib library initialization */

/* Function prototypes */
void Default_Handler(void);
void Reset_Handler(void) __noreturn; /* Reset Handler will never return */

static void CopyDataInit(void);
static void FillZerobss(void);

/* Provide weak aliases for each Exception handler to the Default_Handler */

/* System exception handlers */
__weak __alias(Default_Handler) void NMI_Handler(void);
__weak __alias(Default_Handler) void HardFault_Handler(void);
__weak __alias(Default_Handler) void MemManage_Handler(void);
__weak __alias(Default_Handler) void BusFault_Handler(void);
__weak __alias(Default_Handler) void UsageFault_Handler(void);
__weak __alias(Default_Handler) void SVC_Handler(void);
__weak __alias(Default_Handler) void DebugMon_Handler(void);
__weak __alias(Default_Handler) void PendSV_Handler(void);
__weak __alias(Default_Handler) void SysTick_Handler(void);

/* Peripheral interrupt handlers */
__weak __alias(Default_Handler) void WWDG_IRQHandler(void);
__weak __alias(Default_Handler) void PVD_IRQHandler(void);
__weak __alias(Default_Handler) void TAMPER_IRQHandler(void);
__weak __alias(Default_Handler) void RTC_IRQHandler(void);
__weak __alias(Default_Handler) void FLASH_IRQHandler(void);
__weak __alias(Default_Handler) void RCC_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI0_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI1_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI2_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI3_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI4_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel1_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel2_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel3_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel4_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel5_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel6_IRQHandler(void);
__weak __alias(Default_Handler) void DMA1_Channel7_IRQHandler(void);
__weak __alias(Default_Handler) void ADC1_2_IRQHandler(void);
__weak __alias(Default_Handler) void USB_HP_CAN1_TX_IRQHandler(void);
__weak __alias(Default_Handler) void USB_LP_CAN1_RX0_IRQHandler(void);
__weak __alias(Default_Handler) void CAN1_RX1_IRQHandler(void);
__weak __alias(Default_Handler) void CAN1_SCE_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI9_5_IRQHandler(void);
__weak __alias(Default_Handler) void TIM1_BRK_IRQHandler(void);
__weak __alias(Default_Handler) void TIM1_UP_IRQHandler(void);
__weak __alias(Default_Handler) void TIM1_TRG_COM_IRQHandler(void);
__weak __alias(Default_Handler) void TIM1_CC_IRQHandler(void);
__weak __alias(Default_Handler) void TIM2_IRQHandler(void);
__weak __alias(Default_Handler) void TIM3_IRQHandler(void);
__weak __alias(Default_Handler) void TIM4_IRQHandler(void);
__weak __alias(Default_Handler) void I2C1_EV_IRQHandler(void);
__weak __alias(Default_Handler) void I2C1_ER_IRQHandler(void);
__weak __alias(Default_Handler) void I2C2_EV_IRQHandler(void);
__weak __alias(Default_Handler) void I2C2_ER_IRQHandler(void);
__weak __alias(Default_Handler) void SPI1_IRQHandler(void);
__weak __alias(Default_Handler) void SPI2_IRQHandler(void);
__weak __alias(Default_Handler) void USART1_IRQHandler(void);
__weak __alias(Default_Handler) void USART2_IRQHandler(void);
__weak __alias(Default_Handler) void USART3_IRQHandler(void);
__weak __alias(Default_Handler) void EXTI15_10_IRQHandler(void);
__weak __alias(Default_Handler) void RTC_Alarm_IRQHandler(void);
__weak __alias(Default_Handler) void USBWakeUp_IRQHandler(void);
__weak __alias(Default_Handler) void TIM8_BRK_IRQHandler(void);
__weak __alias(Default_Handler) void TIM8_UP_IRQHandler(void);
__weak __alias(Default_Handler) void TIM8_TRG_COM_IRQHandler(void);
__weak __alias(Default_Handler) void TIM8_CC_IRQHandler(void);
__weak __alias(Default_Handler) void ADC3_IRQHandler(void);
__weak __alias(Default_Handler) void FSMC_IRQHandler(void);
__weak __alias(Default_Handler) void SDIO_IRQHandler(void);
__weak __alias(Default_Handler) void TIM5_IRQHandler(void);
__weak __alias(Default_Handler) void SPI3_IRQHandler(void);
__weak __alias(Default_Handler) void UART4_IRQHandler(void);
__weak __alias(Default_Handler) void UART5_IRQHandler(void);
__weak __alias(Default_Handler) void TIM6_IRQHandler(void);
__weak __alias(Default_Handler) void TIM7_IRQHandler(void);
__weak __alias(Default_Handler) void DMA2_Channel1_IRQHandler(void);
__weak __alias(Default_Handler) void DMA2_Channel2_IRQHandler(void);
__weak __alias(Default_Handler) void DMA2_Channel3_IRQHandler(void);
__weak __alias(Default_Handler) void DMA2_Channel4_5_IRQHandler(void);

/* The Vector Table */
__used __section(.isr_vector) const interruptHandlerType g_pfnVectors[] = {
    /* Core exceptions */
    (void *)_estack,    /**< Initial stack pointer */
    Reset_Handler,      /**< Reset handler */
    NMI_Handler,        /**< Non Maskable Interrupt handler */
    HardFault_Handler,  /**< Hard Fault handler */
    MemManage_Handler,  /**< Memory Management Fault handler */
    BusFault_Handler,   /**< Bus Fault handler */
    UsageFault_Handler, /**< Usage Fault handler */
    NULL,               /**< Reserved */
    NULL,               /**< Reserved */
    NULL,               /**< Reserved */
    NULL,               /**< Reserved */
    SVC_Handler,        /**< SVCall handler */
    DebugMon_Handler,   /**< Debug Monitor handler */
    NULL,               /**< Reserved */
    PendSV_Handler,     /**< PendSV handler */
    SysTick_Handler,    /**< SysTick handler */

    /* External interrupts */
    WWDG_IRQHandler,            /**< Window Watchdog interrupt */
    PVD_IRQHandler,             /**< PVD through EXTI line detection interrupt */
    TAMPER_IRQHandler,          /**< Tamper interrupt */
    RTC_IRQHandler,             /**< RTC global interrupt */
    FLASH_IRQHandler,           /**< Flash global interrupt */
    RCC_IRQHandler,             /**< RCC global interrupt */
    EXTI0_IRQHandler,           /**< EXTI Line0 interrupt */
    EXTI1_IRQHandler,           /**< EXTI Line1 interrupt */
    EXTI2_IRQHandler,           /**< EXTI Line2 interrupt */
    EXTI3_IRQHandler,           /**< EXTI Line3 interrupt */
    EXTI4_IRQHandler,           /**< EXTI Line4 interrupt */
    DMA1_Channel1_IRQHandler,   /**< DMA1 Channel1 interrupt */
    DMA1_Channel2_IRQHandler,   /**< DMA1 Channel2 interrupt */
    DMA1_Channel3_IRQHandler,   /**< DMA1 Channel3 interrupt */
    DMA1_Channel4_IRQHandler,   /**< DMA1 Channel4 interrupt */
    DMA1_Channel5_IRQHandler,   /**< DMA1 Channel5 interrupt */
    DMA1_Channel6_IRQHandler,   /**< DMA1 Channel6 interrupt */
    DMA1_Channel7_IRQHandler,   /**< DMA1 Channel7 interrupt */
    ADC1_2_IRQHandler,          /**< ADC1 and ADC2 global interrupt */
    USB_HP_CAN1_TX_IRQHandler,  /**< USB High Priority or CAN1 TX interrupt */
    USB_LP_CAN1_RX0_IRQHandler, /**< USB Low Priority or CAN1 RX0 interrupt */
    CAN1_RX1_IRQHandler,        /**< CAN1 RX1 interrupt */
    CAN1_SCE_IRQHandler,        /**< CAN1 SCE interrupt */
    EXTI9_5_IRQHandler,         /**< EXTI Line[9:5] interrupts */
    TIM1_BRK_IRQHandler,        /**< TIM1 Break interrupt */
    TIM1_UP_IRQHandler,         /**< TIM1 Update interrupt */
    TIM1_TRG_COM_IRQHandler,    /**< TIM1 Trigger and Commutation interrupts */
    TIM1_CC_IRQHandler,         /**< TIM1 Capture Compare interrupt */
    TIM2_IRQHandler,            /**< TIM2 global interrupt */
    TIM3_IRQHandler,            /**< TIM3 global interrupt */
    TIM4_IRQHandler,            /**< TIM4 global interrupt */
    I2C1_EV_IRQHandler,         /**< I2C1 event interrupt */
    I2C1_ER_IRQHandler,         /**< I2C1 error interrupt */
    I2C2_EV_IRQHandler,         /**< I2C2 event interrupt */
    I2C2_ER_IRQHandler,         /**< I2C2 error interrupt */
    SPI1_IRQHandler,            /**< SPI1 global interrupt */
    SPI2_IRQHandler,            /**< SPI2 global interrupt */
    USART1_IRQHandler,          /**< USART1 global interrupt */
    USART2_IRQHandler,          /**< USART2 global interrupt */
    USART3_IRQHandler,          /**< USART3 global interrupt */
    EXTI15_10_IRQHandler,       /**< EXTI Line[15:10] interrupts */
    RTC_Alarm_IRQHandler,       /**< RTC alarm through EXTI line interrupt */
    USBWakeUp_IRQHandler,       /**< USB wakeup from suspend interrupt */
    TIM8_BRK_IRQHandler,        /**< TIM8 Break interrupt */
    TIM8_UP_IRQHandler,         /**< TIM8 Update interrupt */
    TIM8_TRG_COM_IRQHandler,    /**< TIM8 Trigger and Commutation interrupts */
    TIM8_CC_IRQHandler,         /**< TIM8 Capture Compare interrupt */
    ADC3_IRQHandler,            /**< ADC3 global interrupt */
    FSMC_IRQHandler,            /**< FSMC global interrupt */
    SDIO_IRQHandler,            /**< SDIO global interrupt */
    TIM5_IRQHandler,            /**< TIM5 global interrupt */
    SPI3_IRQHandler,            /**< SPI3 global interrupt */
    UART4_IRQHandler,           /**< UART4 global interrupt */
    UART5_IRQHandler,           /**< UART5 global interrupt */
    TIM6_IRQHandler,            /**< TIM6 global interrupt */
    TIM7_IRQHandler,            /**< TIM7 global interrupt */
    DMA2_Channel1_IRQHandler,   /**< DMA2 Channel1 interrupt */
    DMA2_Channel2_IRQHandler,   /**< DMA2 Channel2 interrupt */
    DMA2_Channel3_IRQHandler,   /**< DMA2 Channel3 interrupt */
    DMA2_Channel4_5_IRQHandler, /**< DMA2 Channel4 and DMA2 Channel5 interrupts */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    NULL,                       /**< Reserved */
    (void *)BootRAM             /**< Boot in RAM mode identifier */
};

/**
 * @brief The default interrupt handler.
 *
 * @param None
 * @return None
 *
 * @note This function is called when an interrupt is triggered that is not handled by any other interrupt handler.
 */
void Default_Handler(void)
{
    while (1)
    {
        /* Infinite loop */
    }
}

/**
 * @brief  This is the code that gets called when the processor first
 *         starts execution following a reset event. Only the absolutely
 *         necessary set is performed, after which the application
 *         supplied main() routine is called.
 * @param  None
 * @retval None
 */
void Reset_Handler(void)
{
    /* Copy the data segment initializers from flash to SRAM */
    CopyDataInit();

    /* Zero fill the bss segment */
    FillZerobss();

    /* Call the clock system initialization function */
    SystemInit();

    /* Call static constructors */
    __libc_init_array();

    /* Call the application's entry point */
    main();

    /* Should never reach here */
    while (1)
    {
        /* Infinite loop */
    }
}

/**
 * @brief  Copy the data segment initializers from flash to SRAM
 * @param  None
 * @retval None
 */
static void CopyDataInit(void)
{
    const uint32_t *src = (void *)_sidata;
    const uint32_t *data_end = (void *)_edata;
    for (uint32_t *p = (void *)_sdata; p < data_end; p++, src++)
    {
        *p = *src;
    }
}

/**
 * @brief  Zero fill the bss segment
 * @param  None
 * @retval None
 */
static void FillZerobss(void)
{
    const uint32_t *bss_end = (void *)_ebss;
    for (uint32_t *p = (void *)_sbss; p < bss_end; p++)
    {
        *p = 0x00;
    }
}
